import 'dart:convert';
import 'package:convert/convert.dart';
import 'dart:math';
import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:encrypt/encrypt.dart';
import 'package:freemusic/model/NeteaseSong.dart';
import 'package:freemusic/model/netease/NeteaseAccount.dart';
import 'package:freemusic/model/netease/NeteaseDiss.dart';

class NeteaseAPI {
  static final String _nonce = "0CoJUm6Qyw8W8jud";
  static final String _secretKey = "EkVpcjVRaEjrJs9g";
  static final String _encSecKey =
      "d2e53ed1d72818936e5680ecf716c8fd58baeea70ce12c0579fabe6d6e562c95df9b72f948744808c8425c43da6a860a308e49509b0ea358c9caef0737539ee70cf8a3831b8ef2005b79ae4ebc4a93d87dea5737cee66d0e81e999e6d19d5255b42d80d732d4978afe7f6df051f4e8c7fd3a9663e2c9eb7672ebe083c4ca86a2";

  static Future<List<NeteaseSong>> search(String keyword, int page) async {
    Response response = await Dio().get(
        "http://music.163.com/api/search/get/web?csrf_token=&lpretag=&hlposttag=&s=$keyword&type=1&offset=${(page - 1) * 10}&total=true&limit=10");
    NeteaseSong song = NeteaseSong();
    return song.fromRemoteJosn(jsonDecode(response.data));
  }

  static Future<NeteaseSong> getSong(NeteaseSong song) async {
    Dio dio = Dio();
    dio.options = BaseOptions(baseUrl: "http://music.163.com/");
    String hash = song.hash.replaceAll("netease_", "");
    song.playUrl =
        "http://music.163.com/song/media/outer/url?id=$hash.${song.type}";

    Response lyricresp =
        await dio.getUri(Uri(path: "/api/song/lyric", queryParameters: {
      "os": "pc",
      "id": "$hash",
      "lv": "-1",
      "tv": "-1",
    }));
    song.lyrics = resolveLyricResponse(lyricresp.data);

    Response imgResponse = await dio.getUri(Uri(
        path: "api/song/detail/",
        queryParameters: {"id": "$hash", "ids": "[$hash]", "csrf_token": ""}));
    song.img = resolveImgResponse(imgResponse.data);

    return song;
  }

  static download(String url, String savepath) async {
    Response response = await Dio().download(url, savepath);
    return response;
  }

  static String resolveLyricResponse(String json) {
    Map lyricrespmap = jsonDecode(json);
    Map lrc = lyricrespmap['lrc'];
    if (lrc == null) {
      return "";
    }
    return lrc['lyric'];
  }

  static String resolveImgResponse(String json) {
    Map result = jsonDecode(json);
    List songs = result['songs'];
    Map album = songs[0]['album'];
    return album['picUrl'] + "?param=300y300";
  }

  static String _generateSecretKey(int size) {
    String keys =
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    String key = "";
    for (int i = 0; i < size; i++) {
      double pos = Random().nextDouble() * keys.length;
      int posInt = pos.floor();
      key = key + keys.substring(posInt, posInt + 1);
    }
    return key;
  }

  static String _aesEncrypt(String text, String seckey) {
    Encrypter encrypter =
        Encrypter(AES(Key.fromUtf8(seckey), mode: AESMode.cbc));
    Encrypted decrypted =
        encrypter.encrypt(text, iv: IV.fromUtf8("0102030405060708"));
    return decrypted.base64;
  }

  static Future<NeteaseAccount> getAccount(
      String account, String password) async {
    password = hex.encode(md5.convert(Utf8Encoder().convert(password)).bytes);
    String paramsJson = "{'phone':'$account','password':'$password'}";
    String params = _aesEncrypt(_aesEncrypt(paramsJson, _nonce), _secretKey);

    Map<String, dynamic> map = Map();
    map['params'] = params;
    map['encSecKey'] = _encSecKey;

    Dio dio = Dio();
    dio.options.headers = {
      "Accept": "*/*",
      "Accept-Encoding": "gzip,deflate,sdch",
      "Accept-Language": "zh-CN,zh;q=0.9",
      "Connection": "keep-alive",
      "Content-Type": "application/x-www-form-urlencoded",
      "Host": "music.163.com",
      "Referer": "https://music.163.com/",
      "User-Agent":
          "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36",
    };

    Response response = await dio.post(
        "https://music.163.com/weapi/login/cellphone?csrf_token=",
        queryParameters: map,
        options: new Options(contentType: "application/x-www-form-urlencoded"));
    NeteaseAccount neteaseAccount = NeteaseAccount();
    neteaseAccount.fromRemoteJosn(response.data);
    return neteaseAccount;
  }

  static Future<List<NeteaseDiss>> getSongSheet(int userId) async {
    String paramsJson = "{'offset':0, 'limit': 100, 'uid': $userId }";
    String params = _aesEncrypt(_aesEncrypt(paramsJson, _nonce), _secretKey);

    Map<String, dynamic> map = Map();
    map['params'] = params;
    map['encSecKey'] = _encSecKey;

    Dio dio = Dio();
    dio.options.headers = {
      "Accept": "*/*",
      "Accept-Encoding": "gzip,deflate,sdch",
      "Accept-Language": "zh-CN,zh;q=0.9",
      "Connection": "keep-alive",
      "Content-Type": "application/x-www-form-urlencoded",
      "Host": "music.163.com",
      "Referer": "https://music.163.com/",
      "User-Agent":
          "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36",
    };
    Response response = await dio.post(
        "https://music.163.com/weapi/user/playlist?csrf_token=",
        queryParameters: map,
        options: new Options(contentType: "application/x-www-form-urlencoded"));

    NeteaseDiss diss = NeteaseDiss();
    return diss.fromRemoteJson(response.data);
  }

  static Future<Map> getDissSongs(int dissId) async {
    String paramsJson = "{'id': $dissId, 'n':10000, 's': 8}";
    String params = _aesEncrypt(_aesEncrypt(paramsJson, _nonce), _secretKey);
    Map<String, dynamic> map = Map();
    map['params'] = params;
    map['encSecKey'] = _encSecKey;

    Dio dio = Dio();
    dio.options.headers = {
      "Accept": "*/*",
      "Accept-Encoding": "gzip,deflate,sdch",
      "Accept-Language": "zh-CN,zh;q=0.9",
      "Connection": "keep-alive",
      "Content-Type": "application/x-www-form-urlencoded",
      "Host": "music.163.com",
      "Referer": "https://music.163.com/",
      "User-Agent":
          "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36",
    };
    Response response = await dio.post("https://music.163.com/weapi/v3/playlist/detail?csrf_token=", queryParameters: map);

    return jsonDecode(response.data);
  }
}
